package server;

import basic.JodisDb;
import com.google.common.base.Stopwatch;
import network.Accepter;
import network.Processor;
import network.RequestHandler;
import protocol.JodisHandler;
import utils.Closeables;
import utils.Logger;
import utils.ThreadUtils;

import java.io.Closeable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

public class JodisServer implements Closeable {
    private Logger logger = Logger.getLogger(JodisServer.class);
    private JodisConfig jodisConfig;
    private final CountDownLatch shutdownLatch = new CountDownLatch(1);
    private AtomicBoolean isShuttingDown = new AtomicBoolean(false);

    //请求处理器
    private RequestHandler requestHandler;
    //事件分发器
    private Processor processor;
    //连接事件接收器
    private Accepter accepter;
    private JodisDb jodisDb;

    public JodisServer(JodisConfig jodisConfig) {
        this.jodisConfig = jodisConfig;
    }

    public void startup(){
        try{
            Stopwatch stopwatch = Stopwatch.createStarted();
            this.jodisDb = new JodisDb(jodisConfig);
            this.requestHandler = new JodisHandler(jodisDb);
            this.processor = new Processor(jodisConfig, requestHandler);
            this.accepter = new Accepter(jodisConfig.getPort(), processor);

            //用两个线程分别去处理事件分发器和连接事件接收器
            ThreadUtils.newThread("jodis-processor",processor,false).start();
            //在run里面执行countDown()
            ThreadUtils.newThread("jodis-acceptor", accepter, false).start();

            //保证连接事件接收器在主线程继续执行前启动起来并run()，使用CountDownLatch
            accepter.awaitStartup();
            logger.info("Jodis server started cost {}", stopwatch.stop().toString());
        }catch (Exception e){
            logger.error("========================================");
            logger.error("Fatal error {} during startup.", e);
            logger.error("========================================");
        }
    }

    /**
     * 关闭jodis服务端
     ***/
    @Override
    public void close(){
        boolean canShutdown = isShuttingDown.compareAndSet(false,true);
        if(!canShutdown) return ;

        logger.info("Shutting down Jodis server...");

        Closeables.closeQuietly(accepter);
        Closeables.closeQuietly(processor);

        //保证关闭前先将资源关闭，然后主线程再继续执行下去
        shutdownLatch.countDown();
        logger.info("Shutdown Jodis server completed");
    }

    public void awaitShutdown() {
        try {
            //得调用countdown()对计数器进行减运算
            shutdownLatch.await();
        } catch (InterruptedException e) {
            logger.warn(e);
        }
    }
}
